//
//  NetViewController.m
//  Common
//
//  Created by fangyuan ding on 2021/11/5.
//

#import "NetViewController.h"

@interface NetViewController ()

@end

@implementation NetViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    //最常见的就是 同步函数 + 主队列 的组合，本质是队列阻塞。
//    dispatch_sync(dispatch_get_main_queue(), ^{
//        NSLog(@"2");
//    });
//
//    NSLog(@"1");
    [self enterAndLeave];
//    [self groupOne];
//    [self groupTwo];
//      [self groupThree];
//    [self groupFour];
//    [self groupFive];
//    [self semaphore];
//    [self semaphoreTwo];
//    [self semaphoreThree];
//    [self barrier];
//    [self syncbarrier];
//    [self asyncbarrier];
  
}

- (void)enterAndLeave{
    //    每次网络请求前先dispatch_group_enter,请求回调后再dispatch_group_leave，enter和leave必须配合使用，有几次enter就要有几次leave，否则group会一直存在。
    //
    //    当所有enter的block都leave后，会执行dispatch_group_notify的block。
        NSString *str = @"https://www.baidu.com";
        NSURL *url = [NSURL URLWithString:str];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        NSURLSession *session = [NSURLSession sharedSession];

        dispatch_group_t downloadGroup = dispatch_group_create();
        for (int i=0; i<10; i++) {
            dispatch_group_enter(downloadGroup);
            
            NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
                NSLog(@"%d---%d",i,i);
                dispatch_group_leave(downloadGroup);
            }];
            [task resume];
        }

        dispatch_group_notify(downloadGroup, dispatch_get_main_queue(), ^{
            NSLog(@"end");
        });
    
}
- (void)groupOne{
    dispatch_queue_t queue = dispatch_queue_create("testqueue", DISPATCH_QUEUE_CONCURRENT);
        dispatch_group_t group = dispatch_group_create();
        
        dispatch_group_async(group, queue, ^{
            for (int i = 0; i < 5; i ++) {
                NSLog(@"任务%d",i);
            }
        });
        
        dispatch_group_async(group, queue, ^{
            NSLog(@"任务5");
        });
        
        dispatch_group_notify(group, queue, ^{
            NSLog(@"全部任务执行完毕");
        });
}
- (void)groupTwo{
    dispatch_queue_t queue = dispatch_queue_create("testqueue", DISPATCH_QUEUE_CONCURRENT);
        dispatch_group_t group = dispatch_group_create();
        
        dispatch_group_async(group, queue, ^{
            dispatch_async(queue, ^{
                for (int i = 0; i < 5; i ++) {
                    NSLog(@"任务%d",i);
                }
            });
        });
        
        dispatch_group_async(group, queue, ^{
            dispatch_async(queue, ^{
                NSLog(@"任务5");
            });
        });
        
        dispatch_group_notify(group, queue, ^{
            NSLog(@"全部任务执行完毕");
        });
}
- (void)groupThree{
    dispatch_queue_t queue = dispatch_queue_create("testqueue", DISPATCH_QUEUE_CONCURRENT);
        dispatch_group_t group = dispatch_group_create();
        dispatch_group_enter(group);
        dispatch_async(queue, ^{
            for (int i = 0; i < 5; i ++) {
                NSLog(@"任务%d",i);
            }
            dispatch_group_leave(group);
        });
        
        dispatch_group_enter(group);
        dispatch_async(queue, ^{
            NSLog(@"任务5");
            dispatch_group_leave(group);
        });
        
        dispatch_group_notify(group, queue, ^{
            NSLog(@"全部任务执行完毕");
        });
}
- (void)groupFour{
    //只采用了dispatch_group_enter,任务一直没有结束
    dispatch_queue_t queue = dispatch_queue_create("testqueue", DISPATCH_QUEUE_CONCURRENT);
        dispatch_group_t group = dispatch_group_create();
        dispatch_group_enter(group);
        dispatch_async(queue, ^{
            for (int i = 0; i < 5; i ++) {
                NSLog(@"任务%d",i);
            }
        });
        
        dispatch_group_enter(group);
        dispatch_async(queue, ^{
            NSLog(@"任务5");
        });
        
        dispatch_group_notify(group, queue, ^{
            NSLog(@"全部任务执行完毕");
        });
}
- (void)groupFive{
    //出现了上面的情况可以采用dispatch_group_leave比dispatch_group_enter成对出现
    dispatch_queue_t queue = dispatch_queue_create("testqueue", DISPATCH_QUEUE_CONCURRENT);
        dispatch_group_t group = dispatch_group_create();
        dispatch_group_enter(group);
        dispatch_async(queue, ^{
            for (int i = 0; i < 5; i ++) {
                NSLog(@"任务%d",i);
                dispatch_group_leave(group);
            }
        });
        
        dispatch_group_enter(group);
        dispatch_async(queue, ^{
            NSLog(@"任务5");
            dispatch_group_leave(group);
        });
        dispatch_group_notify(group, queue, ^{
            NSLog(@"全部任务执行完毕");
        });
}
//信号量
- (void)semaphore{
    
    NSString *str = @"https://www.baidu.com";
    NSURL *url = [NSURL URLWithString:str];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    NSURLSession *session = [NSURLSession sharedSession];

    __block int count = 0;
    dispatch_semaphore_t sem = dispatch_semaphore_create(0);
    for (int i=0; i<10; i++) {
        
        NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            NSLog(@"%d---%d",i,i);
            count++;
            if (count==10) {
                dispatch_semaphore_signal(sem);
                count = 0;
                // 使某个信号的信号量+1
                NSLog(@"signal");
               
            }
        }];
        [task resume];
    }
    // 某个信号进行等待或等待降低信号量 timeout：等待时间，永远等待为 DISPATCH_TIME_FOREVER
    //正常的使用顺序是先降低然后再提高，这两个函数通常成对使用。
    dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
    NSLog(@"wait");

    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"end");
    });
    
}
- (void)semaphoreTwo{
    NSString *str = @"http://www.jianshu.com/p/6930f335adba";
    NSURL *url = [NSURL URLWithString:str];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    NSURLSession *session = [NSURLSession sharedSession];

    dispatch_semaphore_t sem = dispatch_semaphore_create(0);
    for (int i=0; i<10; i++) {
        
        NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            NSLog(@"%d---%d",i,i);
            dispatch_semaphore_signal(sem);
        }];
        
        [task resume];
        dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
    }

    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"end");
    });
}
- (void)semaphoreThree{
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(queue, ^{
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            
            NSLog(@"1任务开始执行");
            
            [NSThread sleepForTimeInterval:3];
            
            NSLog(@"1任务结束执行");

            dispatch_semaphore_signal(semaphore);
            
        });
        
        dispatch_async(queue, ^{
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            
            NSLog(@"2任务开始执行");
            
            [NSThread sleepForTimeInterval:3];
            
            NSLog(@"2任务结束执行");

            dispatch_semaphore_signal(semaphore);
            
        });
        
        dispatch_async(queue, ^{
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            
            NSLog(@"3任务开始执行");
            
            [NSThread sleepForTimeInterval:3];
            
            NSLog(@"3任务结束执行");

            dispatch_semaphore_signal(semaphore);
            
        });
        
        dispatch_async(queue, ^{
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            
            NSLog(@"4任务开始执行");
            
            [NSThread sleepForTimeInterval:3];
            
            NSLog(@"4任务结束执行");

            dispatch_semaphore_signal(semaphore);
            
        });
        
        dispatch_async(queue, ^{
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            
            NSLog(@"5任务开始执行");
            
            [NSThread sleepForTimeInterval:3];
            
            NSLog(@"5任务结束执行");

            dispatch_semaphore_signal(semaphore);
        });
}
- (void)barrier{
    dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);

    dispatch_async(queue, ^{
        NSLog(@"第一次任务的主线程为: %@", [NSThread currentThread]);
    });

    dispatch_async(queue, ^{
        NSLog(@"第二次任务的主线程为: %@", [NSThread currentThread]);
    });

    dispatch_barrier_async(queue, ^{
        NSLog(@"第一次任务, 第二次任务执行完毕, 继续执行");
    });

    dispatch_async(queue, ^{
        NSLog(@"第三次任务的主线程为: %@", [NSThread currentThread]);
    });

    dispatch_async(queue, ^{
        NSLog(@"第四次任务的主线程为: %@", [NSThread currentThread]);
    });
    
}
- (void)syncbarrier{
    dispatch_queue_t queue=dispatch_queue_create("testqueue",DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"start");
    dispatch_async(queue,^{NSLog(@"---test1---");});
    dispatch_async(queue,^{NSLog(@"---test12---");});
    dispatch_barrier_sync(queue,^{NSLog(@"----barrier-----");});
    NSLog(@"aaa");
    dispatch_async(queue,^{NSLog(@"---test3---");});
    dispatch_async(queue,^{NSLog(@"---test4---");});
    NSLog(@"last");
}
- (void)asyncbarrier{
    dispatch_queue_t queue=dispatch_queue_create("testqueue",DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"start");
    dispatch_async(queue,^{NSLog(@"---test1---");});
    dispatch_async(queue,^{NSLog(@"---test12---");});
    dispatch_barrier_async(queue,^{NSLog(@"----barrier-----");});
    NSLog(@"aaa");
    dispatch_async(queue,^{NSLog(@"---test3---");});
    dispatch_async(queue,^{NSLog(@"---test4---");});
    NSLog(@"last");
}
@end
